Jx.categorize('platform.browser.feature', {

	$extend: 'Jx.lib.Support',

	$accessors: {

		'cssComputedStyle': false,

		'cssCurrentStyle': false,

		'cssFilter': false,

		'cssFloat': false,

		'cssOpacity': false,

		'cssStyleSetAttribute': false,

		'cssStyleRemoveAttribute': false,

		'cssStyleSetProperty': false,

		'cssStyleRemoveProperty': false,

		'cssStylePixelBox': false,

		'cssTransparentColor': false,

		'cssRightMargin': false,

		'cssTextareaResize': false,

		'domCompareDocumentPosition': false,

		'domConstains': false,

		'domSourceIndex': false,

		'domEventLevel2': false,

		'domMSEvent': false,

		'domBoundingClientRect': false,

		'domReadyState': false,

		'domDocumentReadyState': false,

		'domCollectionToArray': false,

		'domQuerySelectorAll': false,

		'domGetElementByTagNameNS': false,

		'domGetElementsByClassName': false,

		'domElementIndex': false,

		'domDirect2DBug': false,

		'domInnerSize': false,

		'domRange': false,

		'svg': false,

		'canvas': false,

		'audio': false,

		'video': false,

		'history': false,

		'websocket': false,

		'geolocation': false

	},

	div: null,

	onDetect: function(){

		//-- create sample div
		var div = this.div = document.createElement('div');

		div.innerHTML = '<div style="height:30px;width:50px;"></div>'

			+ '<textarea></textarea>'

			+ '<div style="float:left; background-color:transparent;"></div>';

		this.$super(arguments);

	},

	onAfterDetect: function(){

		//-- to avoid memory leak
		delete this.div;

		this.$super(arguments);

	},

/**
 *	CSS and Style
 */
	detectCssComputedStyle: function(){

		return 'getComputedStyle' in window;

	},

	detectCssCurrentStyle: function(){

		return 'currentStyle' in this.div;

	},

	detectCssFilter: function(){

		return 'filter' in this.div.style;

	},

	detectCssFloat : function(){

		return !!this.div.lastChild.style.cssFloat;

	},

	detectCssOpacity: function(){

		var div = this.div.firstChild;

		div.style.cssText = 'opacity:0.73';

		//-- no IE 8 and below
		return !this.detected.is('ie <= 8') && div.style.opacity == '0.73';

	},

	detectCssStyleSetAttribute: function(){

		return 'setAttribute' in this.div.style;

	},

	detectCssStyleRemoveAttribute: function(){

		return 'removeAttribute' in this.div.style;

	},

	detectCssStyleSetProperty: function(){

		return 'setProperty' in this.div.style;

	},

	detectCssStyleRemoveProperty: function(){

		return 'removeProperty' in this.div.style;

	},


	detectCssStylePixelBox: function(){

		return 'pixelTop' in this.div.style;

	},

	detectCssTransparentColor: function() {

		var view = Jx.GLOBAL,

			last = this.div.lastChild;

		return (

			'getComputedStyle' in view ?

				view.getComputedStyle(last, null)

				:

				last.currentStyle

		).backgroundColor == 'transparent';

	},

	// https://bugs.webkit.org/show_bug.cgi?id=13343 for why this is needed.
	detectCssRightMargin: function() {

		var view = Jx.GLOBAL,

			last = this.div.lastChild;

		return (

			'getComputedStyle' in view ?

				view.getComputedStyle(last, null)

				:

				last.currentStyle

		).marginRight != '0px';

	},

	detectCssTextareaResize: function(){

		return 'resize' in this.div.firstChild.nextSibling.style;

	},

/**
 *	Dom Manipulation
 */

	detectDomCompareDocumentPosition: function(){

		var div = this.div,

			method = 'compareDocumentPosition';

		return method in div.ownerDocument && method in div;

	},

	detectDomContains: function(){

		return 'contains' in this.div;
	},

	detectDomSourceIndex: function(){

		var div = this.div;

		return 'sourceIndex' in div && Jx.isNumber(div.sourceIndex);

	},

	detectDomEventLevel2: function(){

		return 'addEventListener' in this.div;

	},

	detectDomMSEvent: function(){

		return 'attachEvent' in this.div;

	},

	detectDomBoundingClientRect: function() {

		return 'getBoundingClientRect' in this.div;

	},

	detectDomReadyState: function(){

		return 'readyState' in this.div;

	},

	detectDomDocumentReadyState: function(){

		return 'readyState' in this.div.ownerDocument;

	},

	detectDomCollectionToArray: function(doc, div){

		try {

			Array.prototype.slice.call(document.documentElement.childNodes, 0);

			return true;

		} catch(e){

			return false;

		}

	},

	detectDomQuerySelectorAll: function(doc){

		return 'querySelectorAll' in document;

	},


	detectDomGetElementByTagNameNS: function(){

		return 'getElementsByTagNameNS' in document;

	},

	detectDomGetElementsByClassName: function(){

		return 'getElementsByClassName' in document;

	},

	detectDomElementIndex: function(){

		return 'firstElementChild' in document.documentElement;

	},

	detectDomDirect2DBug: function(){

		var s = this.div.style;

		return 'msTransformOrigin' in s && Jx.isString(s.msTransformOrigin);

	},

	detectDomInnerSize: function(){

		return 'innerHeight' in window && Jx.isNumber(window.innerHeight);

	},

	detectDomRange: function(doc, div){

		return 'createRange' in document;

	},

/**
 *	HTML 5
 */

	detectSvg: function() {

		var doc = document;

		return 'createElementNS' in doc &&

			'createSVGRect' in doc.createElementNS( "http://www.w3.org/2000/svg", "svg");

	},

	detectCanvas: function() {

		return 'getContext' in document.createElement('canvas');

	},

	detectAudio: function() {

		return 'canPlayType' in document.createElement('audio');

	},

	detectVideo: function(doc) {

		return 'canPlayType' in document.createElement('video');

	},

	detectHistory: function() {

		return 'pushState' in window.history;

	},

	detectWebsocket: function(){

		return 'WebSocket' in window && WebSocket.OPEN == 1;

	},



/**
 *	misc
 */

	detectGeolocation: function(){

		var view = window;

		return 'geolocation' in view.navigator ||

			('google' in view && 'gears' in view.google);

	}

});
